package org.dval.plugin;

import com.jfinal.aop.Enhancer;
import com.jfinal.aop.Interceptor;
import com.jfinal.config.Routes;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.IPlugin;
import com.jfinal.plugin.activerecord.Model;
import org.dval.annotation.ControllerKey;
import org.dval.annotation.Entity;
import org.dval.annotation.Service;
import org.dval.plugin.ioc.InjectUtils;
import org.dval.plugin.ioc.IocKit;
import org.dval.searcher.ClassSearcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Collection;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

@SuppressWarnings("unchecked")
public class IocPlugin implements IPlugin {

    private String[] pkgs;
    private Routes routes;
    private Interceptor[] interceptors;

    public IocPlugin(Routes routes, String[] pkgs, Interceptor... interceptors) {
        this.pkgs = pkgs;
        this.routes = routes;
        this.interceptors = interceptors;
    }

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    private static final ConcurrentMap<String, Object> iocBeanMap = new ConcurrentHashMap<String, Object>();

    @Override
    public boolean start() {
        logger.info("loading annotaion");
        for (Interceptor inter : this.interceptors) {
            this.routes.addInterceptor(inter);
        }
        Set<Class<?>> classes = ClassSearcher.getClasses(pkgs, ControllerKey.class, Service.class, Entity.class);

        for (Class<?> clazz : classes) {
            String beanName = clazz.getName();
            if (com.jfinal.core.Controller.class.isAssignableFrom(clazz)) {
                initController(clazz);
                continue;
            }
            if (clazz.getAnnotation(Entity.class) != null) {
                try {
                    Model<?> model = (Model<?>) clazz.newInstance();
                    iocBeanMap.put(beanName, model);
                } catch (Exception e) {

                }
                continue;
            }
            if (clazz.getAnnotation(Service.class) != null) {
                Object enhanceBean = Enhancer.enhance(clazz, this.interceptors);
                if (iocBeanMap.containsKey(beanName)) {
                    logger.warn("bean:" + beanName + " reloading!");
                }
                iocBeanMap.put(beanName, enhanceBean);
            }
            continue;
        }
        IocKit.init(iocBeanMap);
        // 处理Bean的相互@Inject

        Collection<Object> beanColl = iocBeanMap.values();
        for (Object object : beanColl) {
            Class<?> superclass;
            if (object.getClass().getAnnotation(Entity.class) != null) {
                superclass = object.getClass();
            } else {
                superclass = object.getClass().getSuperclass();
            }
            InjectUtils.inject(superclass, object);
        }

        logger.info("net.xgs.annotation loaded ");
        return true;
    }

    @Override
    public boolean stop() {
        iocBeanMap.clear();
        return true;
    }
    private void initController(Class<?> clazz) {
        ControllerKey controller = clazz.getAnnotation(ControllerKey.class);
        String viewPath = controller.viewPath();
        if (StrKit.isBlank(viewPath)) {
            viewPath = controller.value();
        }
        routes.add(controller.value(), (Class<? extends com.jfinal.core.Controller>) clazz, viewPath);
    }
}
